
`timescale 1 ns / 1 ps

    module MiniMAC_1Ge_AXI_v1_0 #
    (
        // Users to add parameters here

        // User parameters ends
        // Do not modify the parameters beyond this line


        // Parameters of Axi Slave Bus Interface S00_AXI
        parameter integer C_S00_AXI_DATA_WIDTH  = 32,
        parameter integer C_S00_AXI_ADDR_WIDTH  = 6,

        // Parameters of Axi Slave Bus Interface S00_AXIS
        parameter integer C_S00_AXIS_TDATA_WIDTH    = 32,

        // Parameters of Axi Master Bus Interface M00_AXIS
        parameter integer C_M00_AXIS_TDATA_WIDTH    = 32,
        parameter integer C_M00_AXIS_START_COUNT    = 32
    )
    (
        // Users to add ports here
        
        output wire out_gmii_rstn,
        output wire out_gmii_clk,
        
        (* X_INTERFACE_INFO = "xilinx.com:interface:rgmii:1.0 USER_RGMII TD" *)
        output [3:0] TD, // Ethernet transmit data (required)
        (* X_INTERFACE_INFO = "xilinx.com:interface:rgmii:1.0 USER_RGMII TX_CTL" *)
        output TX_CTL, // Ethernet transmit control (required)
        (* X_INTERFACE_INFO = "xilinx.com:interface:rgmii:1.0 USER_RGMII TXC" *)
        output TXC, // Ethernet transmit clock (required)
        (* X_INTERFACE_INFO = "xilinx.com:interface:rgmii:1.0 USER_RGMII RD" *)
        input [3:0] RD, // Ethernet receive data (required)
        (* X_INTERFACE_INFO = "xilinx.com:interface:rgmii:1.0 USER_RGMII RX_CTL" *)
        input RX_CTL, // Ethernet receive control (required)
        (* X_INTERFACE_INFO = "xilinx.com:interface:rgmii:1.0 USER_RGMII RXC" *)
        input RXC, // Ethernet receive clock (required)
        
        // User ports ends
        // Do not modify the ports beyond this line


        // Ports of Axi Slave Bus Interface S00_AXI
        input wire  s00_axi_aclk,
        input wire  s00_axi_aresetn,
        input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr,
        input wire [2 : 0] s00_axi_awprot,
        input wire  s00_axi_awvalid,
        output wire  s00_axi_awready,
        input wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_wdata,
        input wire [(C_S00_AXI_DATA_WIDTH/8)-1 : 0] s00_axi_wstrb,
        input wire  s00_axi_wvalid,
        output wire  s00_axi_wready,
        output wire [1 : 0] s00_axi_bresp,
        output wire  s00_axi_bvalid,
        input wire  s00_axi_bready,
        input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr,
        input wire [2 : 0] s00_axi_arprot,
        input wire  s00_axi_arvalid,
        output wire  s00_axi_arready,
        output wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_rdata,
        output wire [1 : 0] s00_axi_rresp,
        output wire  s00_axi_rvalid,
        input wire  s00_axi_rready,

        // Ports of Axi Slave Bus Interface S00_AXIS
        input wire  s00_axis_aclk,
        input wire  s00_axis_aresetn,
        output wire  s00_axis_tready,
        input wire [C_S00_AXIS_TDATA_WIDTH-1 : 0] s00_axis_tdata,
        input wire [(C_S00_AXIS_TDATA_WIDTH/8)-1 : 0] s00_axis_tstrb,
        input wire  s00_axis_tlast,
        input wire  s00_axis_tvalid,

        // Ports of Axi Master Bus Interface M00_AXIS
        input wire  m00_axis_aclk,
        input wire  m00_axis_aresetn,
        output wire  m00_axis_tvalid,
        output wire [C_M00_AXIS_TDATA_WIDTH-1 : 0] m00_axis_tdata,
        output wire [(C_M00_AXIS_TDATA_WIDTH/8)-1 : 0] m00_axis_tstrb,
        output wire  m00_axis_tlast,
        input wire  m00_axis_tready
    );
wire [C_S00_AXI_DATA_WIDTH-1:0] s00_axi_reg0;
// Instantiation of Axi Bus Interface S00_AXI
    MiniMAC_1Ge_AXI_v1_0_S00_AXI # ( 
        .C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),
        .C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)
    ) MiniMAC_1Ge_AXI_v1_0_S00_AXI_inst (
        .slv_reg0(s00_axi_reg0),
        .S_AXI_ACLK(s00_axi_aclk),
        .S_AXI_ARESETN(s00_axi_aresetn),
        .S_AXI_AWADDR(s00_axi_awaddr),
        .S_AXI_AWPROT(s00_axi_awprot),
        .S_AXI_AWVALID(s00_axi_awvalid),
        .S_AXI_AWREADY(s00_axi_awready),
        .S_AXI_WDATA(s00_axi_wdata),
        .S_AXI_WSTRB(s00_axi_wstrb),
        .S_AXI_WVALID(s00_axi_wvalid),
        .S_AXI_WREADY(s00_axi_wready),
        .S_AXI_BRESP(s00_axi_bresp),
        .S_AXI_BVALID(s00_axi_bvalid),
        .S_AXI_BREADY(s00_axi_bready),
        .S_AXI_ARADDR(s00_axi_araddr),
        .S_AXI_ARPROT(s00_axi_arprot),
        .S_AXI_ARVALID(s00_axi_arvalid),
        .S_AXI_ARREADY(s00_axi_arready),
        .S_AXI_RDATA(s00_axi_rdata),
        .S_AXI_RRESP(s00_axi_rresp),
        .S_AXI_RVALID(s00_axi_rvalid),
        .S_AXI_RREADY(s00_axi_rready)
    );
    
    // AXI-lite to control signals mapping
    wire phy_link_up   = s00_axi_reg0[0];
    wire phy_giga_mode = s00_axi_reg0[1];

    wire         gen_en     ;
    wire [31: 0] int_data_i ;
    wire         int_valid_i;
    wire         int_sop_i  ;
    wire         int_eop_i  ;
    wire [ 1: 0] int_mod_i  ;
// Instantiation of Axi Bus Interface S00_AXIS
    MiniMAC_1Ge_AXI_v1_0_S00_AXIS # ( 
        .C_S_AXIS_TDATA_WIDTH(C_S00_AXIS_TDATA_WIDTH)
    ) MiniMAC_1Ge_AXI_v1_0_S00_AXIS_inst (
        .int_rst    (!phy_link_up ),  //input  wire
        .int_clk    ( RXC         ),  //input  wire
        .gen_en     ( gen_en      ),  //output reg 
        .int_data   ( int_data_i  ),  //input  wire [31: 0] 
        .int_valid  ( int_valid_i ),  //input  wire         
        .int_sop    ( int_sop_i   ),  //input  wire         
        .int_eop    ( int_eop_i   ),  //input  wire         
        .int_mod    ( int_mod_i   ),  //input  wire [ 1: 0]
                
        .S_AXIS_ACLK(s00_axis_aclk),
        .S_AXIS_ARESETN(s00_axis_aresetn),
        .S_AXIS_TREADY(s00_axis_tready),
        .S_AXIS_TDATA(s00_axis_tdata),
        .S_AXIS_TKEEP(s00_axis_tstrb),
        .S_AXIS_TLAST(s00_axis_tlast),
        .S_AXIS_TVALID(s00_axis_tvalid)
    );

        
    wire         par_en     ;
    wire [31: 0] int_data_o ;
    wire         int_valid_o;
    wire         int_sop_o  ;
    wire         int_eop_o  ;
    wire [ 1: 0] int_mod_o  ;
// Instantiation of Axi Bus Interface M00_AXIS
    MiniMAC_1Ge_AXI_v1_0_M00_AXIS # ( 
        .C_M_AXIS_TDATA_WIDTH(C_M00_AXIS_TDATA_WIDTH),
        .C_M_START_COUNT(C_M00_AXIS_START_COUNT)
    ) MiniMAC_1Ge_AXI_v1_0_M00_AXIS_inst (
        .int_rst    (!phy_link_up ),  //input  wire
        .int_clk    ( RXC         ),  //input  wire
        .par_en     ( par_en      ),  //output reg
        .int_data   ( int_data_o  ),  //output reg  [31: 0] 
        .int_valid  ( int_valid_o ),  //output reg          
        .int_sop    ( int_sop_o   ),  //output reg          
        .int_eop    ( int_eop_o   ),  //output reg          
        .int_mod    ( int_mod_o   ),  //output reg  [ 1: 0]
        
        .M_AXIS_ACLK(m00_axis_aclk),
        .M_AXIS_ARESETN(m00_axis_aresetn),
        .M_AXIS_TVALID(m00_axis_tvalid),
        .M_AXIS_TDATA(m00_axis_tdata),
        .M_AXIS_TKEEP(m00_axis_tstrb),
        .M_AXIS_TLAST(m00_axis_tlast),
        .M_AXIS_TREADY(m00_axis_tready)
    );

    // Add user logic here
        
    // DUT    
    mac_top dut (
        .rst(!phy_link_up),
        .clk(RXC),
        
        .phy_giga_mode(phy_giga_mode),  
        
        .gen_en       ( gen_en      ),  //output reg 
        .int_data_i   ( int_data_i  ),  //input  wire [31: 0] 
        .int_valid_i  ( int_valid_i ),  //input  wire         
        .int_sop_i    ( int_sop_i   ),  //input  wire         
        .int_eop_i    ( int_eop_i   ),  //input  wire         
        .int_mod_i    ( int_mod_i   ),  //input  wire [ 1: 0]
    
        .par_en       ( par_en      ),  //output reg
        .int_data_o   ( int_data_o  ),  //output reg  [31: 0] 
        .int_valid_o  ( int_valid_o ),  //output reg          
        .int_sop_o    ( int_sop_o   ),  //output reg          
        .int_eop_o    ( int_eop_o   ),  //output reg          
        .int_mod_o    ( int_mod_o   ),  //output reg  [ 1: 0]
    
        `ifdef ENABLE_INTERNAL_PHY
        .gmii_rxclk (),  //input  wire          
        .gmii_rxctrl(),  //input  wire          
        .gmii_rxdata(),  //input  wire [ 7: 0]  
        .gmii_txclk (),  //output wire          
        .gmii_txctrl(),  //output wire          
        .gmii_txdata()   //output wire [ 7: 0]  
        `else
        .rgmii_rxclk (RXC   ),  //input  wire         
        .rgmii_rxctrl(RX_CTL),  //input  wire         
        .rgmii_rxdata(RD    ),  //input  wire [ 3: 0] 
        .rgmii_txclk (TXC   ),  //output wire         
        .rgmii_txctrl(TX_CTL),  //output wire         
        .rgmii_txdata(TD    )   //output wire [ 3: 0] 
        `endif
    
    );

    assign out_gmii_rstn = phy_link_up;
    assign out_gmii_clk  = RXC;

    // User logic ends

    endmodule
